﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.IO;

using Tubes4_Metnum.Util;

namespace Tubes4_Metnum
{
    public class ProgramUtil
    {
        private StringBuilder expressionBuilder;
        private double h;
        private double c;
        private double k;
        private double[] PKimia;
        private double[] CKimia;
        private String interpolasiCExpKimia;
        private String ExpKimia;
        public double[] PKimiaArray 
        {
            get { return this.PKimia; }
        }
        public double[] CKimiaArray
        {
            get { return this.CKimia; }
        }
        
        public ProgramUtil()
        {
            expressionBuilder = new StringBuilder();
            h = 6.6256 * Math.Pow(10, -27);
            c = 2.99792 * Math.Pow(10, 10);
            k = 1.3805 * Math.Pow(10, -16);
            PKimia = new double[] { 1, 10, 20, 40, 60, 80, 120, 160, 250, 400 };
            CKimia = new double[] { 0.9940, 0.9370, 0.8683, 0.7043, 0.4515, 0.3429, 0.4529, 0.5252, 0.7468, 1.0980 };
            interpolasiCExpKimia = null;
            ExpKimia = null;
        }

        public bool CheckMetode(MetodeEnum metode, int n)
        {
            if (metode == MetodeEnum.Simpson1per3)
            {
                return (n % 2 == 0);
            }
            else if (metode == MetodeEnum.Simpson3per8)
            {
                return (n % 3 == 0);
            }
            else if (metode == MetodeEnum.Romberg)
            {
                if (n % 2 == 1)
                {
                    return false;
                }
                else
                {
                    int temp = 1;
                    while (temp < n)
                    {
                        temp = temp * 2;
                    }
                    return (temp == n);
                }
            }
            return true;
        }

        public MetodeEnum FindMetode(int n)
        {
            if (n % 3 == 0) // Kelipatan 3
            {
                return MetodeEnum.Simpson3per8;
            } 
            else if (n % 2 == 0) // Kelipatan 2
            {
                return MetodeEnum.Simpson1per3;
            }
            return MetodeEnum.TitikTengah; // Bebas, Tidak terkait N
        }

        public String CreateFisika1Exp(double a, double b, int T)
        {
            expressionBuilder.Clear();

            double temp = 2 * Math.PI * h * c * c * (b - a);
            // expressionBuilder.Append(temp.ToString(CultureInfo.GetCultureInfo("en-US")));
            expressionBuilder.Append(temp);
            expressionBuilder.Append("/");
            expressionBuilder.Append("(");
            expressionBuilder.Append("(x^5)*(exp");
            expressionBuilder.Append("(");
            temp = h * c;
            // expressionBuilder.Append(temp.ToString(CultureInfo.GetCultureInfo("en-US")));
            expressionBuilder.Append(temp);
            expressionBuilder.Append("/");
            temp = k * T;
            // expressionBuilder.Append("((" + temp.ToString(CultureInfo.GetCultureInfo("en-US")) + ")*x)");
            expressionBuilder.Append("((" + temp + ")*x)");
            expressionBuilder.Append(")");
            expressionBuilder.Append("-1)");
            expressionBuilder.Append(")");
            return expressionBuilder.ToString();
        }

        public String CreateKimiaExp(int n)
        {
            if (ExpKimia == null)
            {
                expressionBuilder.Clear();

                //double C_int = CKimia[0];
                //for (int i = 0; i < this.PKimia.Length; i++)
                //{
                //    if (this.PKimia[i] == P)
                //    {
                //        C_int = CKimia[i];
                //    }
                //}

                interpolasiCExpKimia = Lagrange.InterpolasiExp(PKimia, CKimia, n);
                expressionBuilder.Append("((" + interpolasiCExpKimia + ")-1)");
                expressionBuilder.Append("/");
                expressionBuilder.Append("x");

                ExpKimia = expressionBuilder.ToString();
            }
            return ExpKimia;
        }

        public void CreateDataKimia(int n, out double[] dataX, out double[] dataY)
        {
            dataX = new double[2];
            dataY = new double[2];
        }


        public String CreateFisika2Exp()
        {
            expressionBuilder.Clear();

            expressionBuilder.Append("1/");
            expressionBuilder.Append("((");
            expressionBuilder.Append("1-");
            expressionBuilder.Append("("); 
            expressionBuilder.Append("(sin("+(Math.PI/20/2)+"))^2");
            expressionBuilder.Append("*");
            expressionBuilder.Append("(sin(x))^2");
            expressionBuilder.Append(")");
            expressionBuilder.Append(")^(1/2))");
            
            return expressionBuilder.ToString();
        }

        public void CreateDataFisika2(out double[] dataX, out double[] dataY)
        {
            dataX = new double[10];
            dataY = new double[10];
            double iterator = 0;

            for (int i = 0; i < dataX.Length; i++)
            {
                iterator = (i + 1) / 20.0; 
                dataX[i] = Math.PI * iterator;
                dataY[i] = 1 / (Math.Sqrt(1 - (Math.Pow(Math.Sin(Math.PI / 20.0 / 2.0), 2.0) * Math.Pow(Math.Sin(dataX[i]), 2.0))));
                // Console.WriteLine("Pembagi (1/Iterator): "+ (1 / iterator));
                // Console.WriteLine("X: " + dataX[i] + "; F(x): " + dataY[i]);
            }
        }

        public String[] CreateKelistrikanExp(double T)
        {
            expressionBuilder.Clear();

            expressionBuilder.Append("(");
            expressionBuilder.Append(10.0);
            expressionBuilder.Append("*");
            expressionBuilder.Append("exp(x/" + T + ")");
            expressionBuilder.Append("*");
            expressionBuilder.Append("sin("+ (2 * Math.PI / T) + "*x)");
            expressionBuilder.Append(")^2");

            String[] exp = new String[2];
            exp[0] = expressionBuilder.ToString();
            exp[1] = "0";
            return exp;
        }

        public String CreateIntegralKelistrikanExpression(double T)
        {
            expressionBuilder.Clear();
            
            expressionBuilder.Append("(");
            expressionBuilder.Append(5.0);
            expressionBuilder.Append("*");
            expressionBuilder.Append("exp(x/" + T + ")");
            expressionBuilder.Append("*");
            expressionBuilder.Append("(sin(" + (2 * Math.PI / T) + "*x)-cos(" + (2 * Math.PI / T) + "*x))");
            expressionBuilder.Append(")^2");

            return expressionBuilder.ToString();
        }

        public double[] CreateDataX(double a, double b, double n, double min_a, double max_b)
        {
            List<double> tempDataXList = new List<double>();
            double h = (b - a) / n; // h asli
            double temp;
            a = (!double.IsInfinity(min_a) && min_a > a) ? min_a : a;
            b = (!double.IsInfinity(max_b) && max_b < b) ? max_b : b;
            temp = a;
            while (temp <= b)
            {
                tempDataXList.Add(temp);
                temp += h;
            }
            return tempDataXList.ToArray();
        }

        public double[][] openTable(String filePath)
        { 
            double[][] result = new double[2][];
            TextReader tr = null;
            try
            {
                tr = new StreamReader(filePath);
                String temp = tr.ReadLine();
                String[] temp1 = temp.Split('-');
                temp = tr.ReadLine();
                String[] temp2 = temp.Split('-');
                int length = (temp1.Length <= temp2.Length) ? temp1.Length : temp2.Length;
                result[0] = new double[length];
                result[1] = new double[length];
                for (int i = 0; i < temp1.Length; i++)
                {
                    result[0][i] = Double.Parse(temp1[i]);
                    result[1][i] = Double.Parse(temp2[i]);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                tr.Close();
            }
            
            return result;
        }
    }

}
